using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;

namespace PdfLib
{
    /// <summary>
    /// major output from pdf reader
    /// </summary>
    public class PdfPage
    {
        #region properties
        private string _FilePath;
        /// <summary>
        /// pdf file path
        /// </summary>
        public string FilePath
        {
            get
            {
                return this._FilePath;
            }
            set
            {
                this._FilePath = value;
            }
        }

        private int _PageNumber;
        /// <summary>
        /// current page num (starting from 1)
        /// </summary>
        public int PageNumber
        {
            get { return _PageNumber; }
            set { _PageNumber = value; }
        }

        private SizeF _PageSize;
        /// <summary>
        /// size in em
        /// </summary>
        public SizeF PageSize
        {
            get { return _PageSize; }
            set { _PageSize = value; }
        }

        private PageOrentation _Orentation;
        /// <summary>
        /// either portrait or landscape
        /// </summary>
        public PageOrentation Orentation
        {
            get { return _Orentation; }
            set { _Orentation = value; }
        }

        private List<PdfTextToken> _TextTokens;
        /// <summary>
        /// info about word, position, bounding rect, font
        /// </summary>
        public List<PdfTextToken> TextTokens
        {
            get
            {
                return _TextTokens;
            }
            set
            {
                _TextTokens = value;
            }
        }

        private bool _IsScannedDoc;
        /// <summary>
        /// determine if the current page contains a scanned image and 
        /// text is behind the image
        /// </summary>
        public bool IsScannedDoc
        {
            get
            {
                return _IsScannedDoc;
            }
            set
            {
                _IsScannedDoc = value;
            }
        }

        private float _PageHeaderHeight;
        /// <summary>
        /// header
        /// </summary>
        public float PageHeaderHeight
        {
            get
            {
                return _PageHeaderHeight;
            }
            set
            {
                _PageHeaderHeight = value;
            }
        }

        private float _PageFooterHeight;
        /// <summary>
        /// page footer
        /// </summary>
        public float PageFooterHeight
        {
            get
            {
                return _PageFooterHeight;
            }
            set
            {
                _PageFooterHeight = value;
            }
        }

        private float _LeftEdge;
        /// <summary>
        /// left edge
        /// </summary>
        public float PageLeftEdgeWidth
        {
            get
            {
                return _LeftEdge;
            }
            set
            {
                _LeftEdge = value;
            }
        }

        private float _RightEdge;
        /// <summary>
        /// right edge
        /// </summary>
        public float PageRightEdgeWidth
        {
            get
            {
                return _RightEdge;
            }
            set
            {
                _RightEdge = value;
            }
        }

        private List<Font> _Fonts;
        /// <summary>
        /// pdf fonts used in current page
        /// </summary>
        public List<Font> Fonts
        {
            get
            {
                return _Fonts;
            }
            set
            {
                _Fonts = value;
            }
        }

        private List<VerticalLine> _VerticalLines;
        /// <summary>
        /// v-lines
        /// </summary>
        public List<VerticalLine> VerticalLines
        {
            get
            {
                return _VerticalLines;
            }
            set
            {
                _VerticalLines = value;
            }
        }

        private List<HorizontalLine> _HorizontalLines;
        /// <summary>
        /// h-lines
        /// </summary>
        public List<HorizontalLine> HorizontalLines
        {
            get
            {
                return _HorizontalLines;
            }
            set
            {
                _HorizontalLines = value;
            }
        }

        private List<RectangleF> _Rects;
        /// <summary>
        /// rects inferred from pdf path or image processing
        /// </summary>
        public List<RectangleF> Rectangles
        {
            get
            {
                return _Rects;
            }
            set
            {
                _Rects = value;
            }
        }
        #endregion

        #region ctor
        public PdfPage(string filePath, int pageNum)
        {
            this._FilePath = filePath;
            this._PageNumber = pageNum;

            try
            {
                this.PageSize = PdfPropertyReader.GetPageSize(this.FilePath, this.PageNumber);
                this.Orentation = PdfPropertyReader.GetPageOrentation(this.FilePath, this.PageNumber);
                this.PageLeftEdgeWidth = 0f;
                this.PageRightEdgeWidth = 0f;
                this.PageHeaderHeight = 0f;
                this.PageFooterHeight = 0f;
                this.TextTokens = PdfTextReader.ReadPageContentAsTokens(this.FilePath, this.PageNumber);
                
                this._Fonts = new List<Font>();
                if (this.TextTokens != null && this.TextTokens.Count > 0)
                {
                    foreach (PdfTextToken token in this.TextTokens)
                    {
                        if (!string.IsNullOrEmpty(token.FontName))
                        {
                            Font font = new Font(new FontFamily(token.FontName), token.FontSize);
                            if (!this._Fonts.Contains(font))
                            {
                                this._Fonts.Add(font);
                            }
                        }
                    }
                }

                Image pageImg = PdfImageReader.GetPageImage(this.FilePath, this.PageNumber);
                if (pageImg != null)
                {
                    this._IsScannedDoc = true;
                    ImageProcesser imgReader = new ImageProcesser(new Bitmap(pageImg), this.PageSize);
                    this._VerticalLines = imgReader.ReadVerticalLines();
                    this._HorizontalLines = imgReader.ReadHorizontalLines();
                    List<Rectangle> rects = imgReader.ReadRectangles();
                    if (rects != null && rects.Count > 0)
                    {
                        this.Rectangles = new List<RectangleF>();
                        foreach (Rectangle rect in rects)
                        {
                            this.Rectangles.Add(new RectangleF(0, 0, rect.Width, rect.Height));
                        }
                    }
                }
                else
                {
                    this._IsScannedDoc = false;
                    if (PdfDrawingInstructionReader.HaveDrawingInstructionsInPage(this.FilePath, this.PageNumber))
                    {
                        this._VerticalLines = PdfDrawingInstructionReader.GetVLines(this.FilePath, this.PageNumber);
                        this._HorizontalLines = PdfDrawingInstructionReader.GetHLines(this.FilePath, this.PageNumber);
                        this._Rects = PdfDrawingInstructionReader.GeRectangles(this.FilePath, this.PageNumber);
                    }
                    else
                    {
                        this._VerticalLines = null;
                        this._HorizontalLines = null;
                        this._Rects = null;
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Unable to retrieve pdf page: " + ex.ToString());
            }
        }
        #endregion
    }
}
